using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using FuncWorks.Xna.Input;
using FuncWorks.Xna.UI;

namespace GuitarAndDrumDemo {
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont font;

        public Game1() {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize() {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent() {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            font = Content.Load<SpriteFont>("SpriteFont1");
            XnaConsole.Font = font;

            Guitar g = new Guitar(PlayerIndex.Four);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent() {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime) {
            Guitar[] guitars = Guitar.Discover();
            foreach (Guitar guitar in guitars) {
                XnaConsole.WriteLine("{0} connected a guitar (IsAlternateGuitar: {1})", guitar.Name, guitar.IsAlternateGuitar);
            }

            DrumKit[] drums = DrumKit.Discover();
            foreach (DrumKit drum in drums) {
                XnaConsole.WriteLine("{0} connected a drumkit", drum.Name);
            }

            foreach (Guitar guitar in Guitar.ActiveGuitars) {
                guitar.Update();
                if (guitar.State.IsButtonDown(Buttons.Back)) { Exit(); }

                foreach (Buttons b in new Buttons[] { Buttons.DPadLeft, Buttons.DPadRight, Buttons.RightShoulder, Buttons.DPadUp, Buttons.DPadDown, Buttons.RightShoulder, Buttons.LeftStick, Buttons.RightStick }) {
                    if (guitar.State.IsButtonDown(b)) { XnaConsole.WriteLine("{0} pressed {1}", guitar.Name, b); }
                }

                if (guitar.StrumUp == GuitarStrumState.Begin || guitar.StrumDown == GuitarStrumState.Begin) {
                    string strumType = (guitar.StrumUp == GuitarStrumState.Begin) ? "upstrum" : "downstrum";

                    List<string> buttonsPressed = new List<string>();
                    if (guitar.Green != GuitarStrumState.None && guitar.Green != GuitarStrumState.Ending) { buttonsPressed.Add("Green"); }
                    if (guitar.Red != GuitarStrumState.None && guitar.Red != GuitarStrumState.Ending) { buttonsPressed.Add("Red"); }
                    if (guitar.Yellow != GuitarStrumState.None && guitar.Yellow != GuitarStrumState.Ending) { buttonsPressed.Add("Yellow"); }
                    if (guitar.Blue != GuitarStrumState.None && guitar.Blue != GuitarStrumState.Ending) { buttonsPressed.Add("Blue"); }
                    if (guitar.Orange != GuitarStrumState.None && guitar.Orange != GuitarStrumState.Ending) { buttonsPressed.Add("Orange"); }
                    if (buttonsPressed.Count == 0) { buttonsPressed.Add("no buttons"); }
                    XnaConsole.WriteLine("{0} started {1} with {2} pressed", guitar.Name, strumType, String.Join("/", buttonsPressed.ToArray()));
                }
                else if (guitar.StrumUp == GuitarStrumState.Continuing || guitar.StrumDown == GuitarStrumState.Continuing) {
                    List<string> buttonsPressed = new List<string>();
                    if (guitar.Green == GuitarStrumState.Begin) { buttonsPressed.Add("Green"); }
                    if (guitar.Red == GuitarStrumState.Begin) { buttonsPressed.Add("Red"); }
                    if (guitar.Yellow == GuitarStrumState.Begin) { buttonsPressed.Add("Yellow"); }
                    if (guitar.Blue == GuitarStrumState.Begin) { buttonsPressed.Add("Blue"); }
                    if (guitar.Orange == GuitarStrumState.Begin) { buttonsPressed.Add("Orange"); }
                    if (buttonsPressed.Count > 0) { XnaConsole.WriteLine("{0} pressed {1}", guitar.Name, String.Join("/", buttonsPressed.ToArray())); }

                    buttonsPressed = new List<string>();
                    if (guitar.Green == GuitarStrumState.Ending) { buttonsPressed.Add("Green"); }
                    if (guitar.Red == GuitarStrumState.Ending) { buttonsPressed.Add("Red"); }
                    if (guitar.Yellow == GuitarStrumState.Ending) { buttonsPressed.Add("Yellow"); }
                    if (guitar.Blue == GuitarStrumState.Ending) { buttonsPressed.Add("Blue"); }
                    if (guitar.Orange == GuitarStrumState.Ending) { buttonsPressed.Add("Orange"); }
                    if (buttonsPressed.Count > 0) { XnaConsole.WriteLine("{0} released {1}", guitar.Name, String.Join("/", buttonsPressed.ToArray())); }
                }
                else if (guitar.StrumUp == GuitarStrumState.Ending || guitar.StrumDown == GuitarStrumState.Ending) {
                    string strumType = (guitar.StrumUp == GuitarStrumState.Begin) ? "upstrum" : "downstrum";
                    XnaConsole.WriteLine("{0} ended {1}", guitar.Name, strumType);
                }
            }

            foreach (DrumKit drum in DrumKit.ActiveKits) {
                drum.Update();
                if (drum.State.IsButtonDown(Buttons.Back)) { Exit(); }

                List<string> padsHit = new List<string>();
                if (drum.Red) { padsHit.Add("Red"); }
                if (drum.Yellow) { padsHit.Add("Yellow"); }
                if (drum.Blue) { padsHit.Add("Blue"); }
                if (drum.Orange) { padsHit.Add("Orange"); }
                if (drum.Green) { padsHit.Add("Green"); }
                if (drum.Pedal) { padsHit.Add("Pedal"); }
                if (padsHit.Count > 0) { XnaConsole.WriteLine("{0} hit {1} pad(s)", drum.Name, String.Join("/", padsHit.ToArray())); }
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime) {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            XnaConsole.Draw(graphics, spriteBatch);

            if (Guitar.ActiveGuitars.Count > 0) {
                spriteBatch.DrawString(font, "Guitar 1", new Vector2(500, 0), Color.White);
                spriteBatch.DrawString(font, "Left X: " + Guitar.ActiveGuitars[0].State.ThumbSticks.Left.X.ToString(), new Vector2(500, 20), Color.White);
                spriteBatch.DrawString(font, "Left Y: " + Guitar.ActiveGuitars[0].State.ThumbSticks.Left.Y.ToString(), new Vector2(500, 40), Color.White);
                spriteBatch.DrawString(font, "Right X: " + Guitar.ActiveGuitars[0].State.ThumbSticks.Right.X.ToString(), new Vector2(500, 60), Color.White);
                spriteBatch.DrawString(font, "Right Y: " + Guitar.ActiveGuitars[0].State.ThumbSticks.Right.Y.ToString(), new Vector2(500, 80), Color.White);
                spriteBatch.DrawString(font, "Left Trig: " + Guitar.ActiveGuitars[0].State.Triggers.Left.ToString(), new Vector2(500, 100), Color.White);
                spriteBatch.DrawString(font, "Right Trig: " + Guitar.ActiveGuitars[0].State.Triggers.Right.ToString(), new Vector2(500, 120), Color.White);
                spriteBatch.DrawString(font, "Roll: " + MathHelper.ToDegrees((float)Guitar.ActiveGuitars[0].RollAngle).ToString(), new Vector2(500, 140), Color.White);
            }

            if (DrumKit.ActiveKits.Count > 0) {
                spriteBatch.DrawString(font, "Drums 1", new Vector2(500, 160), Color.White);
                spriteBatch.DrawString(font, "Left X: " + DrumKit.ActiveKits[0].State.ThumbSticks.Left.X.ToString(), new Vector2(500, 300), Color.White);
                spriteBatch.DrawString(font, "Left Y: " + DrumKit.ActiveKits[0].State.ThumbSticks.Left.Y.ToString(), new Vector2(500, 320), Color.White);
                spriteBatch.DrawString(font, "Right X: " + DrumKit.ActiveKits[0].State.ThumbSticks.Right.X.ToString(), new Vector2(500, 340), Color.White);
                spriteBatch.DrawString(font, "Right Y: " + DrumKit.ActiveKits[0].State.ThumbSticks.Right.Y.ToString(), new Vector2(500, 360), Color.White);
                spriteBatch.DrawString(font, "Left Trig: " + DrumKit.ActiveKits[0].State.Triggers.Left.ToString(), new Vector2(500, 380), Color.White);
                spriteBatch.DrawString(font, "Right Trig: " + DrumKit.ActiveKits[0].State.Triggers.Right.ToString(), new Vector2(500, 400), Color.White);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
